<script setup lang="tsx">
import { ContentWrap } from '@/components/ContentWrap'
import { useI18n } from '@/hooks/web/useI18n'
import { Table, TableColumn } from '@/components/Table'
import { computed, nextTick, reactive, ref, unref, watch } from 'vue'
import { ElDivider, ElInput, ElTree, ElTag, ElMessage, ElMessageBox } from 'element-plus'
import { getSelfDepartmentApi } from '@/api/department'
import type { DepartmentItem } from '@/api/department/types'
import { useTable } from '@/hooks/web/useTable'
import { Search } from '@/components/Search'
import Write from './components/Write.vue'
import Detail from './components/Detail.vue'
import { Dialog } from '@/components/Dialog'
import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
import { BaseButton } from '@/components/Button'
import { listToTree } from '@/utils/tree'
import { useDictStoreWithOut } from '@/store/modules/dict'
import { getUserByIdApi, resetDefaultPasswordApi, saveUserApi } from '@/api/user'
import { UserItem, UserParams, UserSaveData } from '@/api/user/types'
import { Log } from '@/utils/logError'
import { useLocaleStoreWithOut } from '@/store/modules/locale'
import { CalculateCellWidth } from '@/utils/calculateCellWidth'

const { t } = useI18n()
useDictStoreWithOut()
const { tableRegister, tableState, tableMethods } = useTable({
  fetchDataApi: async () => {
    const { pageSize, currentPage } = tableState
    // 构建参数对象
    const params: Record<string, any> = {
      pageNum: unref(currentPage),
      pageSize: unref(pageSize),
      ...unref(searchParams)
    }
    // 只有当 currentNodeKey 有值时才添加 departmentId 参数
    if (unref(currentNodeKey)) {
      params.departmentId = unref(currentNodeKey)
    }
    const { data, pagination } = await getUserByIdApi(params as UserParams)
    return {
      list: Array.isArray(data) ? data : [],
      total: pagination?.total || 0
    }
  }
})
const { total, loading, dataList, pageSize, currentPage } = tableState
const { getList } = tableMethods

const actionWidth = computed(() => {
  const useLocaleStore = useLocaleStoreWithOut()
  return CalculateCellWidth([
    { permission: 'user:update', width: 86 },
    { permission: 'user:detail', width: 86 },
    {
      permission: 'user:update:reset-password',
      width: useLocaleStore.getCurrentLocale.lang === 'en' ? 70 : 130
    }
  ])
})

const tableColumns = reactive<TableColumn[]>([
  {
    field: 'index',
    label: t('common.tableIndex'),
    type: 'index'
  },
  {
    field: 'name',
    label: t('user.name')
  },
  {
    field: 'username',
    label: t('user.account')
  },
  {
    field: 'role',
    label: t('role.role'),
    slots: {
      default: (data: any) => {
        return (
          data.row?.roles?.map?.(({ code, name }) => (
            <ElTag key={code} class="mr-2px">
              {name}
            </ElTag>
          )) ?? null
        )
      }
    }
  },
  {
    field: 'email',
    label: t('common.email')
  },
  {
    field: 'phone',
    label: t('personalCenter.phone'),
    slots: {
      default: (data: any) => {
        return data.row.phone || '-'
      }
    }
  },
  {
    field: 'remark',
    label: t('common.remark'),
    slots: {
      default: (data: any) => {
        return data.row.remark || '-'
      }
    }
  },
  {
    field: 'status',
    label: t('common.status'),
    slots: {
      default: (data: any) => {
        return (
          <ElTag type={data.row.status ? 'success' : 'danger'} class="mr-2px">
            {data.row.status ? t('common.enable') : t('common.disable')}
          </ElTag>
        )
      }
    }
  },
  {
    field: 'action',
    label: t('common.action'),
    width: actionWidth.value,
    slots: {
      default: (data: any) => {
        return (
          <>
            <BaseButton
              type="primary"
              v-prem={{ value: 'user:update' }}
              onClick={() => action(data.row, 'edit')}
            >
              {t('common.edit')}
            </BaseButton>
            <BaseButton
              type="success"
              v-prem={{ value: 'user:detail' }}
              onClick={() => action(data.row, 'detail')}
            >
              {t('common.detail')}
            </BaseButton>
            <BaseButton
              type="success"
              v-prem={{ value: 'user:update:reset-password' }}
              onClick={() => action(data.row, 'reset')}
            >
              {t('user.resetPassword')}
            </BaseButton>
          </>
        )
      }
    }
  }
])

const crudSchemas = reactive<CrudSchema[]>([
  {
    field: 'name',
    label: t('user.name')
  },
  {
    field: 'username',
    label: t('user.account')
  }
])

const { allSchemas } = useCrudSchemas(crudSchemas)

const searchParams = ref({})
const setSearchParams = (params: any) => {
  currentPage.value = 1
  searchParams.value = params
  getList()
}

const resettingTree = ref(false)

const resetSearchParams = () => {
  searchParams.value = {}
  currentPage.value = 1
  currentNodeKey.value = undefined
  resettingTree.value = true
  unref(treeEl)?.setCurrentKey(null)
  nextTick(() => {
    resettingTree.value = false
  })
  getList()
}

const treeEl = ref<typeof ElTree>()

const currentNodeKey = ref<number | undefined>(undefined)
const departmentList = ref<DepartmentItem[]>([])
const fetchDepartment = async () => {
  const res = await getSelfDepartmentApi()
  departmentList.value = listToTree(res.data || [], { pid: 'parentDeptId' })
  await nextTick()
  unref(treeEl)?.setCurrentKey(currentNodeKey.value)
}
fetchDepartment()

const currentDepartment = ref('')
watch(
  () => currentDepartment.value,
  (val) => {
    unref(treeEl)!.filter(val)
  }
)

const currentChange = (data: DepartmentItem) => {
  // 如果正在重置树组件，则不执行后续逻辑
  if (unref(resettingTree)) return
  currentNodeKey.value = data?.id || undefined
  currentPage.value = 1
  getList()
}

interface Tree {
  [key: string]: any
}

const filterNode = (value: string, data: Tree) => {
  if (!value) return true
  return data.name.includes(value)
}

const dialogVisible = ref(false)
const dialogTitle = ref('')

const currentId = ref<number | null>(null)
const actionType = ref('')

const AddAction = () => {
  dialogTitle.value = t('common.add')
  currentId.value = null
  dialogVisible.value = true
  actionType.value = ''
}

const resetDefaultPasswordEvent = async () => {
  try {
    await ElMessageBox.confirm(t('user.resetPasswordConfirm'), t('common.notice'), {
      confirmButtonText: t('common.ok'),
      cancelButtonText: t('common.cancel'),
      type: 'warning'
    })
    const result = await resetDefaultPasswordApi(currentId.value as number)
    ElMessage.success(result.message)
    await getList()
  } catch (error) {
    if (error === 'cancel') return {}
    Log.error('resetDefaultPasswordEvent', error)
    ElMessage.error(t('common.failed'))
  }
}

const action = (row: UserItem, type: string) => {
  currentId.value = row.id
  if (type === 'reset') return resetDefaultPasswordEvent()
  actionType.value = type
  dialogTitle.value = t(type === 'edit' ? 'common.edit' : 'common.detail')
  dialogVisible.value = true
}

const writeRef = ref<ComponentRef<typeof Write>>()

const saveLoading = ref(false)

const save = async () => {
  const write = unref(writeRef)
  const formData = await write?.submit()

  if (formData) {
    const deleteKeys = ['createdAt', 'updatedAt', 'departmentName']
    deleteKeys.forEach((key) => {
      delete formData[key]
    })
    saveLoading.value = true
    try {
      const result = await saveUserApi(formData as UserSaveData)
      ElMessage.success(result.message)
      currentPage.value = 1
      await getList()
    } catch (error) {
      Log.error('Update User', error)
    } finally {
      saveLoading.value = false
      dialogVisible.value = false
    }
  }
}
</script>

<template>
  <div class="flex w-100% h-100%">
    <ContentWrap class="w-250px">
      <div class="flex justify-center items-center">
        <div class="flex-1">{{ t('department.list') }}</div>
        <ElInput
          v-model="currentDepartment"
          class="flex-[2]"
          :placeholder="t('department.searchDepartment')"
          clearable
        />
      </div>
      <ElDivider />
      <ElTree
        ref="treeEl"
        :data="departmentList"
        default-expand-all
        :expand-on-click-node="false"
        node-key="id"
        highlight-current
        :current-node-key="currentNodeKey"
        :props="{
          label: 'departmentName'
        }"
        :filter-node-method="filterNode"
        @current-change="currentChange"
      >
        <template #default="{ data }">
          <div
            :title="data.departmentName"
            class="whitespace-nowrap overflow-ellipsis overflow-hidden"
          >
            {{ data.name }}
          </div>
        </template>
      </ElTree>
    </ContentWrap>
    <ContentWrap class="flex-[3] ml-20px" v-prem="'user:page'">
      <Search
        :schema="allSchemas.searchSchema"
        @reset="resetSearchParams"
        @search="setSearchParams"
      />

      <div class="mb-10px">
        <BaseButton type="primary" v-prem="'user:create'" @click="AddAction">
          {{ t('common.add') }}
        </BaseButton>
      </div>
      <Table
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :columns="tableColumns"
        :data="dataList"
        :loading="loading"
        @register="tableRegister"
        :pagination="{
          total
        }"
      />
    </ContentWrap>

    <Dialog v-model="dialogVisible" :title="dialogTitle">
      <Write v-if="actionType !== 'detail'" ref="writeRef" :current-id="currentId || 0" />
      <Detail v-if="actionType === 'detail'" :current-id="currentId || 0" />

      <template #footer>
        <BaseButton
          v-if="actionType !== 'detail'"
          type="primary"
          v-prem="['user:create', 'user:update']"
          :loading="saveLoading"
          @click="save"
        >
          {{ t('common.save') }}
        </BaseButton>
        <BaseButton @click="dialogVisible = false">{{ t('common.close') }}</BaseButton>
      </template>
    </Dialog>
  </div>
</template>
